////////////////////////////////////////////////////////////////////////////////

#ifndef _CLIENTGUI_H_
#define _CLIENTGUI_H_

////////////////////////////////////////////////////////////////////////////////

#ifndef _GRAPHICS_H_
#include "graphics.h"
#endif

#ifndef _INPUT_H_
#include "input.h"
#endif

#ifndef _TIMER_H_
#include "timer.h"
#endif

#ifndef _MUTEX_H_
#include "mutex.h"
#endif

#ifndef _CLIENTBATTLEFIELD_H_
#include "clientbattlefield.h"
#endif

#ifndef _SERVERSTATE_H_
#include "serverstate.h"
#endif

#include <queue>

////////////////////////////////////////////////////////////////////////////////

class Client;
class ServerStatePacket;
class ClientInputPacket;

////////////////////////////////////////////////////////////////////////////////


/** Client GUI and INPUT
*
*
*  @author   Roman Pasechnik
*  @since    Jun 11th, 2009
*  @updated  Nov 12th, 2009
*/
class ClientGUI : public Observer
{
////////////////////////////////////////////////////////////////////////////////

public:

////////////////////////////////////////////////////////////////////////////////


    /** Constructor */
    ClientGUI();
    
    
    /** Destructor */
    ~ClientGUI();

    
////////////////////////////////////////////////////////////////////////////////


    /** Start GUI */
    void Start( Client* _client );


////////////////////////////////////////////////////////////////////////////////


    /** Get client input */
    const ClientInput& GetClientInput() const;
 

////////////////////////////////////////////////////////////////////////////////


    /** Render queue */
    void Render();


    /** Add data to render queue */
    void AddToRenderQueue( const ServerStatePacket& _packet );


////////////////////////////////////////////////////////////////////////////////

private:    
    
////////////////////////////////////////////////////////////////////////////////
//// Observer interface implementation
////////////////////////////////////////////////////////////////////////////////


    /** Notify observer about event */
    virtual void OnEvent( Event _event, Observable* _observable );


////////////////////////////////////////////////////////////////////////////////


    /** Key changed handler */
    void OnKeyChanged();


    /** Key changed handler */
    void OnMousePositionChanged();


    /** Load images */
    void LoadImages();


    /** Start game loop */
    void RunGameLoop();


////////////////////////////////////////////////////////////////////////////////


    /** [Utility type]: Pointer to next battlefield state
        from render queue and coefficient, telling where exactly are we
        between current and next states. */
    typedef std::pair< const ServerState*, double > NextBattlefieldState;


    /** Get first two states from render queue and alpha coefficient */
    NextBattlefieldState GetNextStateFromQueue();


    /** Render battlefield */
    void RenderBattlefield();


////////////////////////////////////////////////////////////////////////////////


    /** Graphics */
    Graphics m_Graphics;


    /** Player image */
    Graphics::Object m_Player;


    /** Bullet image */
    Graphics::Object m_Bullet;


    /** Background image */
    Graphics::Object m_Background;



////////////////////////////////////////////////////////////////////////////////


    /** Input */
    Input m_Input;


    /** Process input events */
    void ProcessInput();


////////////////////////////////////////////////////////////////////////////////


    /** Timer for repeating game loop */
    Timer m_Timer;


    /** [Utility type]: Battlefield state and time of its creation */
    typedef std::pair<size_t, ServerState> RenderState;


    /** [Utility type]: Queue of render states */
    typedef std::deque<RenderState> RenderQueue;


    /** Render queue */
    RenderQueue m_RenderQueue;


    /** Render queue mutex */
    Mutex m_RenderQueueMutex;


    /** Client input */
    ClientInput m_ClientInput;


    /** Client interface */
    Client* m_Client;


    /** Client battlefield */
    ClientBattlefield m_Battlefield;


    /** Stop game? */
    bool m_Stop;


////////////////////////////////////////////////////////////////////////////////
};


////////////////////////////////////////////////////////////////////////////////

#endif

////////////////////////////////////////////////////////////////////////////////

